/*
 * @Version: 1.0
 * @Author: ZPK
 * @Date: 2022-11-13 14:23:38
 * @LastEditors: ZPK
 * @LastEditTime: 2022-11-16 21:10:30
 */
// 类：类的组成部分，构造函数，属性(实例属性，原型属性) 方法(实例方法，原型方法 访问器)

// 所有实例上的属性都需要先声明再使用
class Circle{ 
 //默认值 可选参数 剩余运算法
 x:number = 0
 y:number = 0
 constructor(x:number,y:number=0,...args:number[]){
    // this.x = x
    // this.y = y
 }
}
let circle = new Circle(100)
circle.y

// 类的修饰符 public(公开的:我自己，我的儿子，外界)  protected(受保护的：我自己，我儿子)  private(私有的：我自己的) readonly(只读的)

class Animal{
    // public name!:string
    // public age!:number
    // constructor(name:string,age:number){
    //     this.name = name
    //     this.age = age
    // }
    // 简写  直接在参数中添加 public privite protected 这些属性会默认添加到实例
    constructor(public readonly name:string,public age:number){
        // 因为在构造函数中是初始化阶段，readonly的值是可以修改的
        this.name = 'add'
    }
    changeNage(name:string){
        this.name = name //这里如果是readonly属性 则不能再修改了
    }
}
class Cat extends Animal{
    public address = 'xxx' //属性
    constructor(name:string,age:number){
        super(name,age) //Animal.call(this,name,age)
        this.address = '美国'
        this.name = 'aaa'
    }
    speak(){

    }
}
let cat = new Cat('Tom',10)

// 属性：实例属性 静态属性  原型属性
// 实例和原型的区别：原型的是共享的 实例的每个人都有的

class Animal1{
    static type = '哺乳类'
    private _name:string = 'Tom'
    // 类中如何声明原型属性？  需要看编译后的代码 Object.difeinproperty(Animal1.prototype,'name',{})
    // 类的访问器
    get name(){
        return this._name
    }
    set name(newValue){
        this._name = newValue
    }
}
let animal1 = new Animal1()
let animal2 = new Animal1()
console.log(Animal1.type);


// 子类中重写父类的方法 1.要求必须和父类的方法类型一致
class Animal2{
    // say():string{
    //     return 'a'
    // }
    say():void{//或者 2.使用void 不关心返回值,只有在类中可以这样
        console.log('父的say');
    } 
    static getType(){
        console.log('父类');
        return '哺乳类'
    }
    public eat:()=>void
    constructor(){
        this.eat = ()=>{}
    }
   
}
class Mouse extends Animal2{
    static getType(){
        console.log('子类');
        super.getType() //相当于是Animal2.getType
        return '哺乳类'
    }
    say(): string {
        console.log('子的say');
        super.say() //在这里super指的是父类的原型
        return 'b'
    }
}
console.log(Animal2.getType());

// super关键字：代表的是父类  或者父类的原型

// 正常类中：原型属性(get xxx 属性访问器来实现)  原型方法 Animal.prototype
// 实例属性 实例方法 声明在实例上
// 静态属性 静态方法 类上的
// super在构造函数中 静态方法中super指向的是父类
// 在原型方法中super指向的是父类的原型

// 思想：组合大于继承



// 构造函数中增加了 private和protected意味着不能再被new了
// 使用功能场景：1.单例模式
class Singleton{
    static instance = new Singleton()
    private constructor(){}
    static getInstance(){
        return this.instance
    }
}
// 单例模式
let instance1 = Singleton.getInstance()
let instance2 = Singleton.getInstance()
console.log(instance1 === instance2);

// 不能被new的可以曹勇抽象类 抽象类中可以采用抽象方法
abstract class Person{
    // 抽象类中可以有非抽象的方法
    drink(){
        console.log('drink');
    }
    // 查看  ------------------------------存在疑问？？？？？？？？？？
    // abstract eat()=>void
    abstract eat():void //需要子类来实现一个eat方法

}
class Teacher extends Person{
    eat():void{

    }
}










export{}    